import { Component } from '../core/Component';
import { GameObject } from '../core/GameObject';
import { SpriteData, SpriteFrame } from './types';

export interface SpriteOptions {
    /**
     * 精灵数据
     */
    data: SpriteData;
    
    /**
     * 初始帧索引
     */
    frameIndex?: number;
    
    /**
     * 是否循环播放
     */
    loop?: boolean;
    
    /**
     * 播放速度倍率
     */
    speed?: number;
    
    /**
     * 是否自动播放
     */
    autoPlay?: boolean;
    
    /**
     * 是否可见
     */
    visible?: boolean;
    
    /**
     * 透明度
     */
    alpha?: number;
    
    /**
     * 混合模式
     */
    compositeOperation?: GlobalCompositeOperation;
}

export class Sprite extends Component {
    protected data: SpriteData;
    protected currentFrame: SpriteFrame;
    protected frameIndex: number;
    protected frameTime: number;
    protected isPlaying: boolean;
    protected loop: boolean;
    protected speed: number;
    protected visible: boolean;
    protected alpha: number;
    protected compositeOperation: GlobalCompositeOperation;
    
    constructor(gameObject: GameObject, options: SpriteOptions) {
        super(gameObject);
        
        this.data = options.data;
        this.frameIndex = options.frameIndex ?? 0;
        this.frameTime = 0;
        this.isPlaying = options.autoPlay ?? false;
        this.loop = options.loop ?? true;
        this.speed = options.speed ?? 1;
        this.visible = options.visible ?? true;
        this.alpha = options.alpha ?? 1;
        this.compositeOperation = options.compositeOperation ?? 'source-over';
        
        // 设置初始帧
        this.currentFrame = this.getFrame(this.frameIndex);
    }
    
    /**
     * 获取指定索引的帧
     */
    private getFrame(index: number): SpriteFrame {
        const { frameWidth, frameHeight } = this.data;
        const framesPerRow = Math.floor(this.data.image.width / frameWidth);
        const row = Math.floor(index / framesPerRow);
        const col = index % framesPerRow;
        
        return {
            x: col * frameWidth,
            y: row * frameHeight,
            width: frameWidth,
            height: frameHeight,
            duration: 100 // 默认帧持续时间
        };
    }
    
    /**
     * 播放动画
     */
    public play(): void {
        this.isPlaying = true;
    }
    
    /**
     * 暂停动画
     */
    public pause(): void {
        this.isPlaying = false;
    }
    
    /**
     * 停止动画并重置到第一帧
     */
    public stop(): void {
        this.isPlaying = false;
        this.frameIndex = 0;
        this.frameTime = 0;
        this.currentFrame = this.getFrame(this.frameIndex);
    }
    
    /**
     * 设置当前帧
     */
    public setFrame(frame: SpriteFrame | number): void {
        if (typeof frame === 'number') {
            if (frame >= 0 && frame < this.getTotalFrames()) {
                this.frameIndex = frame;
                this.frameTime = 0;
                this.currentFrame = this.getFrame(this.frameIndex);
            }
        } else {
            this.currentFrame = frame;
        }
    }
    
    /**
     * 获取当前帧
     */
    public getCurrentFrame(): SpriteFrame {
        return this.currentFrame;
    }
    
    /**
     * 获取播放状态
     */
    public getIsPlaying(): boolean {
        return this.isPlaying;
    }
    
    /**
     * 设置播放状态
     */
    public setIsPlaying(playing: boolean): void {
        this.isPlaying = playing;
    }
    
    /**
     * 获取可见性
     */
    public getVisible(): boolean {
        return this.visible;
    }
    
    /**
     * 获取播放速度
     */
    public getSpeed(): number {
        return this.speed;
    }
    
    /**
     * 获取总帧数
     */
    public getTotalFrames(): number {
        const { frameWidth, frameHeight, image } = this.data;
        const framesPerRow = Math.floor(image.width / frameWidth);
        const rows = Math.floor(image.height / frameHeight);
        return framesPerRow * rows;
    }
    
    /**
     * 设置可见性
     */
    public setVisible(visible: boolean): void {
        this.visible = visible;
    }
    
    /**
     * 设置透明度
     */
    public setAlpha(alpha: number): void {
        this.alpha = Math.max(0, Math.min(1, alpha));
    }
    
    /**
     * 设置混合模式
     */
    public setCompositeOperation(operation: GlobalCompositeOperation): void {
        this.compositeOperation = operation;
    }
    
    /**
     * 更新组件
     */
    public update(deltaTime: number): void {
        if (!this.isPlaying || !this.visible) {
            return;
        }
        
        // 更新帧时间
        this.frameTime += deltaTime * this.speed;
        
        // 检查是否需要切换到下一帧
        if (this.frameTime >= (this.currentFrame.duration ?? 100)) {
            this.frameTime = 0;
            this.frameIndex++;
            
            // 检查是否需要循环
            if (this.frameIndex >= this.getTotalFrames()) {
                if (this.loop) {
                    this.frameIndex = 0;
                } else {
                    this.frameIndex = this.getTotalFrames() - 1;
                    this.isPlaying = false;
                }
            }
            
            this.currentFrame = this.getFrame(this.frameIndex);
        }
    }
    
    /**
     * 渲染组件
     */
    public render(ctx: CanvasRenderingContext2D): void {
        if (!this.visible) {
            return;
        }
        
        // 保存当前状态
        ctx.save();
        
        // 设置混合模式和透明度
        ctx.globalCompositeOperation = this.compositeOperation;
        ctx.globalAlpha = this.alpha;
        
        // 获取游戏对象的位置和缩放
        const transform = this.gameObject.transform;
        const position = transform.position;
        const scale = transform.scale;
        const rotation = transform.rotation;
        
        // 设置变换
        ctx.translate(position.x, position.y);
        ctx.rotate(rotation);
        ctx.scale(scale.x, scale.y);
        
        // 绘制精灵帧
        const { image } = this.data;
        const { x, y, width, height } = this.currentFrame;
        ctx.drawImage(
            image,
            x, y, width, height,
            -width / 2, -height / 2, width, height
        );
        
        // 恢复状态
        ctx.restore();
    }
    
    /**
     * 销毁组件
     */
    public destroy(): void {
        // 清理资源
        this.data = null!;
        this.currentFrame = null!;
        super.destroy();
    }
} 